#include <iostream>

#include "edaBestImprSelect.h"
#include "edaHC.h"
#include "edaSA.h"
#include "edaSequentialControl.h"
#include "edaExpCoolingSchedule.h"
#include "edaGenContinue.h"
#include "graph.h"
#include "mySolution.h"
#include "myTwoOpt.h"
#include "myTwoOptNext.h"
#include "myTwoOptMoveRandom.h"

int main(int argc, char **argv)
{
  if (argc != 2) {
    std::cerr << "Usage : ./mySFSearch [instance]" << std::endl;
    return 1;
  }

  srand(1000);

  Graph::load(argv[1]);

  mySolution route;

  std::cout << "[From] " << route << std::endl;

  myTwoOpt two_opt;
  edaBestImprSelect moveSelect;
  myTwoOptNext two_opt_next;
  edaHC hcSearch(&two_opt, &two_opt_next, &moveSelect);

  myTwoOpt two_opt1, two_opt2;
  myTwoOptMoveRandom two_opt_random1, two_opt_random2;
  edaExpCoolingSchedule coolingSchedule1(0.01, 0.90), coolingSchedule2(0.01, 0.90);
  edaGenContinue cont_criteria1(1000), cont_criteria2(1000);
  edaSA saSearch1(&two_opt1, &two_opt_random1, &cont_criteria1, 
		 1100.0, &coolingSchedule1);
  edaSA saSearch2(&two_opt2, &two_opt_random2, &cont_criteria2, 
		 1500.0, &coolingSchedule2);

  edaSequentialControl sfControl;
  int hcid1 = sfControl.insertVertex( &hcSearch );
  int hcid2 = sfControl.insertVertex( &hcSearch );
  int said1 = sfControl.insertVertex( &saSearch1 );
  int said2 = sfControl.insertVertex( &saSearch2 );
  sfControl.insertEdge( hcid1, said1 ); 
  sfControl.insertEdge( hcid1, said2 );
  sfControl.insertEdge( said1, hcid2 );
  sfControl.insertEdge( said2, hcid2 );

  sfControl.search(route);

  std::cout << "[To] " << route << std::endl;
  std::cout << "[To Fitness] " << route.fullEvaluate() << std::endl;

  return 0;
}

